package org.naxx.security.util;

import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;

import org.apache.log4j.Logger;

public final class FileSystemUtil {
	
	private static final Logger logger = Logger.getLogger(FileSystemUtil.class);
	
	/**
	 * Converts absolute files names into strings.
	 */
	public static String[] filesToStrings(File[] files) {
		String[] result = new String[files.length];
		for (int i = 0; i < files.length; i++) {
			result[i] = files[i].getAbsolutePath();
		}
		return result;
	}
	
	public static void createFolder(String folderName) {
		Assert.assertNotNullAndHasLenght(folderName, "Illegal folder name '" + folderName + "'.");
		File folder = new File(folderName);
		if(folder.exists()) {
			throw new IllegalArgumentException("Can't create folder '" + folderName 
					+ "' because it already exists");
		}
		if(!folder.mkdir()) {
			throw new IllegalStateException("Failed to create folder names '" + folderName 
					+ "'.");
		}
		logger.info("Folder '" + folderName + "' successfully created");
	}
	
	/**
	 * It will first check if file exists and is readable by
	 * calling <code>Assert.assertFileExistsAndReadable(file)</code>.
	 */
	public static byte[] getFileBytes(String fileName) {
		File file = new File(fileName);
		Assert.assertFileExistsAndReadable(file);
		InputStream in = null;
		try {
			in = new FileInputStream(file);
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			int bite = -1;
			while((bite = in.read()) != -1) { // TODO buffering
				baos.write(bite);
			}
			return baos.toByteArray();
		} catch (Exception e) {
			throw new IllegalArgumentException("Exception while reading from file" +
					" '" + fileName + "'", e);
		}
		finally {
			close(in);
		}
	}
	
	/**
	 * Does not traverse sub-directories.
	 */
	public static void deleteFilesFromDirectory(File directory) {
		File[] files = directory.listFiles();
		logger.info("Preparing to delete " + files.length + " files from " +
				"folder '" + directory.getAbsolutePath() + "'");
		for (File file : files) {
			if(file.delete()) {
				logger.info("File '" + file.getAbsolutePath() + "' successfully deleted");
			}
			else {
				logger.info("Could not delete file '" + file.getAbsolutePath() + "'");
			}
		}
	}
	
	/**
	 * Close closeable and swallow but log any exception
	 * that might occur.
	 */
	public static void close(Closeable closeable) {
		if(closeable != null) {
			try {
				closeable.close();
			} catch (Exception e) {
				logger.warn("Exception while trying to close closeable, swallowed.", e);
			}
		}
	}
	
	/**
	 * Close XML event reader and swallow but log any exception
	 * that might occur.
	 */
	public static void release(XMLEventWriter writer) {
		if(writer != null) {
			try {
				writer.close();
			} catch (Throwable t) {
				logger.warn("Exception while trying to close XML event writer, swallowed.", t);
			}
		}
	}
	
	/**
	 * Close XML event reader and swallow but log any exception
	 * that might occur.
	 */
	public static void release(XMLEventReader reader) {
		if(reader != null) {
			try {
				reader.close();
			} catch (Throwable t) {
				logger.warn("Exception while trying to close XML event reader, swallowed.", t);
			}
		}
	}
	
	private FileSystemUtil() {
		throw new IllegalStateException("Can not instantiate class '" 
				+ FileSystemUtil.class.getCanonicalName() + "'.");
	}
}
